package com.banciyuan.bcywebview.base.view.tag;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Build;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.banciyuan.bcywebview.R;
import com.banciyuan.bcywebview.utils.common.UIUtils;

import java.util.ArrayList;
import java.util.List;

import de.greenrobot.daoexample.model.TagDetail;

/**
 * Created by squall on 2016/4/25.
 */
public class TagView extends View {

    private static final int DEFAULT_BORDER_COLOR = Color.TRANSPARENT;
    private static final int ORIGIN_PADDING = 2;
    private int mMaxLinesCount;
    private int mHorizontalSpacing;
    private int mVerticalSpacing;
    private int total_width;
    private int lines = 1;
    private int text_paddingleft;
    private int text_paddingRight;
    private int border_height;
    private int border_radius;
    private int border_background_color;
    private int icon_padding_left;
    private int icon_padding_right;
    private int icon_width;
    private int text_size;
    private int lines_color;
    private int text_color;
    private int work_line_color;
    private int event_line_color;
    private int work_text_color;
    private int event_text_color;
    private int work_label;
    private int event_label;
    private boolean is_show_icon;
    private boolean keep_height;
    private boolean ellipsize;

    private Paint paint;
    private Paint back;
    private Paint textPaint;
    private Paint imagePaint;

    private Bitmap work_bitmap;
    private Bitmap event_bitmap;
    private RectF rectTag = new RectF();
    private RectF rectImage = new RectF();

    private OnTagClickListener tagClickListener;

    private List<TagDetail> tlist = new ArrayList<>();

    public TagView(Context context) {
        super(context);
    }

    public TagView(Context context, AttributeSet attrs) {
        super(context, attrs);
        getAttr(context, attrs);
        setPaint();
        setLabel();
    }

    public TagView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        getAttr(context, attrs);
        setPaint();
        setLabel();

    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public TagView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        getAttr(context, attrs);
        setPaint();
        setLabel();

    }

    public void setTlist(List<TagDetail> tlist) {
        this.tlist = deepCopy(tlist);
        for (TagDetail t : this.tlist) {
            t.setShow_name(t.getTag_name());
        }
        requestLayout();
    }

    private List<TagDetail> deepCopy(List<TagDetail> list) {
        List<TagDetail> copy = new ArrayList<>();
        for (TagDetail element : list) {
            TagDetail clone = (TagDetail) element.clone();
            clone.setRect(clone.new Rect());
            copy.add(clone);
        }
        return copy;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        try {
            if (tlist.size() > 0) {
                int top = getPaddingTop() + UIUtils.dip2px(ORIGIN_PADDING, getContext()) / 2;
                int left = getPaddingLeft() + UIUtils.dip2px(ORIGIN_PADDING, getContext()) / 2;
                Bitmap bitmap = null;
                int width = left;
                int height = top;
                for (TagDetail t : tlist) {
                    int border_width = 0;
                    if (is_show_icon && (!TextUtils.isEmpty(t.getWork()) || !TextUtils.isEmpty(t.getEvent_id()))) {
                        if (!TextUtils.isEmpty(t.getWork())) {
                            paint.setColor(work_line_color);
                            textPaint.setColor(work_text_color);
                            bitmap = work_bitmap;
                        } else {
                            paint.setColor(lines_color);
                            textPaint.setColor(text_color);
                            bitmap = event_bitmap;
                        }
                        border_width = getIconWidth(t.getTag_name(), textPaint);
                    } else {
                        border_width = getTextWidth(t.getTag_name(), textPaint);
                        paint.setColor(lines_color);
                        textPaint.setColor(text_color);
                    }
                    if (border_width > total_width && total_width > 0) {
                        border_width = minusWord(t, textPaint, left);
                    }
                    if (border_width + width > total_width && total_width > 0) {
                        height += border_height + mVerticalSpacing;
                        width = left;
                        if (mMaxLinesCount == 1) {
                            break;
                        }
                    }
                    rectTag.set(width, height, border_width + width, border_height + height);
                    float baseline = (rectTag.bottom + rectTag.top - textPaint.getFontMetrics().bottom - textPaint.getFontMetrics().top) / 2;
                    if (border_background_color != Color.TRANSPARENT) {
                        canvas.drawRoundRect(rectTag, border_radius, border_radius, back);
                    }
                    canvas.drawRoundRect(rectTag, border_radius, border_radius, paint);
                    if ((!TextUtils.isEmpty(t.getWork()) || !TextUtils.isEmpty(t.getEvent_id())) && is_show_icon) {
                        int imageHeight = Math.round(border_height / 2) + height - Math.round(icon_width / 2);
                        rectImage.set(width + icon_padding_left, imageHeight, width + icon_padding_left + icon_width, imageHeight + icon_width);
                        if (bitmap != null) {
                            canvas.drawBitmap(bitmap, null, rectImage, imagePaint);
                        }
                        canvas.drawText(t.getShow_name(), icon_padding_left + icon_padding_right + icon_width + width, baseline, textPaint);
                    } else {
                        canvas.drawText(t.getShow_name(), text_paddingleft + width, baseline, textPaint);
                    }
                    width += border_width + mHorizontalSpacing;
                    t.setRect(rectTag);
                    if (ellipsize && t.isEllipsize()) {
                        break;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        try {
            lines = 1;
            total_width = MeasureSpec.getSize(widthMeasureSpec) - getPaddingRight();
            int width = getPaddingLeft();
            if (total_width > 0) {
                if (mMaxLinesCount != 1) {
                    for (TagDetail t : tlist) {
                        int border_width = 0;
                        if (is_show_icon && (!TextUtils.isEmpty(t.getWork()) || !TextUtils.isEmpty(t.getEvent_id()))) {
                            border_width = getIconWidth(t.getTag_name(), textPaint);
                        } else {
                            border_width = getTextWidth(t.getTag_name(), textPaint);
                        }
                        if (border_width > total_width) {
                            border_width = minusWord(t, textPaint, getPaddingLeft());
                        }
                        if (border_width + width > total_width) {
                            width = getPaddingLeft();
                            lines++;
                        }
                        width += border_width + mHorizontalSpacing;
                    }

                } else {
                    lines = 1;
                    for (int i = 0; i < tlist.size(); i++) {
                        TagDetail t = tlist.get(i);
                        int border_width = 0;
                        if (is_show_icon && (!TextUtils.isEmpty(t.getWork()) || !TextUtils.isEmpty(t.getEvent_id()))) {
                            border_width = getIconWidth(t.getTag_name(), textPaint);
                        } else {
                            border_width = getTextWidth(t.getTag_name(), textPaint);
                        }
                        if (border_width > total_width) {
                            border_width = minusWord(t, textPaint, getPaddingLeft());
                        }
                        if (t.isEllipsize()) {
                            width += getTextWidth("...", textPaint) + mHorizontalSpacing;
                            break;
                        }
                        if (border_width + width > total_width) {
                            if (ellipsize && i - 1 > 0) {
                                TagDetail pre = tlist.get(i - 1);
                                pre.setShow_name("...");
                                pre.setTag_name("...");
                                pre.setEllipsize(true);
                                width += getTextWidth("...", textPaint) + mHorizontalSpacing;
                            }
                            break;
                        }
                        width += border_width + mHorizontalSpacing;
                    }
                }
            }

            if (MeasureSpec.AT_MOST == MeasureSpec.getMode(widthMeasureSpec)) {
                widthMeasureSpec = MeasureSpec.makeMeasureSpec(width + getPaddingRight(), MeasureSpec.EXACTLY);
            }
            int height = 0;
            if (tlist.size() > 0 || keep_height) {
                height = lines * border_height + (lines - 1) * mVerticalSpacing + getPaddingTop() + getPaddingBottom() + UIUtils.dip2px(ORIGIN_PADDING, getContext());
                setMeasuredDimension(widthMeasureSpec, height);
            } else {
                height = getPaddingTop() + getPaddingBottom();
                setMeasuredDimension(widthMeasureSpec, height);
            }
        } catch (Exception e) {
            e.printStackTrace();
            setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
        }

    }

    private void setPaint() {
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStrokeWidth(2);
        paint.setStyle(Paint.Style.STROKE);

        back = new Paint(Paint.ANTI_ALIAS_FLAG);
        back.setColor(border_background_color);
        back.setStyle(Paint.Style.FILL);

        textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        textPaint.setTextSize(text_size);

        imagePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    }

    private void setLabel() {
        work_bitmap = BitmapFactory.decodeResource(getResources(), work_label);
        event_bitmap = BitmapFactory.decodeResource(getResources(), event_label);
    }

    private void getAttr(Context context, AttributeSet attrs) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TagView);
        mMaxLinesCount = a.getInteger(R.styleable.TagView_t_maxline, Integer.MAX_VALUE);
        mHorizontalSpacing = (int) a.getDimension(R.styleable.TagView_t_horizontal_spacing, UIUtils.dip2px(6, getContext()));
        mVerticalSpacing = (int) a.getDimension(R.styleable.TagView_t_vertical_spacing, UIUtils.dip2px(6, getContext()));
        text_paddingleft = (int) a.getDimension(R.styleable.TagView_t_text_padding_left, UIUtils.dip2px(10, getContext()));
        text_paddingRight = (int) a.getDimension(R.styleable.TagView_t_text_padding_right, UIUtils.dip2px(10, getContext()));
        border_height = (int) a.getDimension(R.styleable.TagView_t_border_height, UIUtils.dip2px(24, getContext()));
        border_radius = (int) a.getDimension(R.styleable.TagView_t_border_radius, UIUtils.dip2px(2, getContext()));
        icon_padding_left = (int) a.getDimension(R.styleable.TagView_t_icon_padding_left, UIUtils.dip2px(8, getContext()));
        icon_padding_right = (int) a.getDimension(R.styleable.TagView_t_icon_padding_right, UIUtils.dip2px(4, getContext()));
        border_background_color = a.getColor(R.styleable.TagView_t_border_background, getResources().getColor(R.color.label_blue));
        icon_width = (int) a.getDimension(R.styleable.TagView_t_icon_width, UIUtils.dip2px(10, getContext()));
        text_size = (int) a.getDimension(R.styleable.TagView_t_text_size, UIUtils.sp2px(12, getContext()));
        lines_color = a.getColor(R.styleable.TagView_t_line_color, getResources().getColor(R.color.label_blue));
        text_color = a.getColor(R.styleable.TagView_t_text_color, getResources().getColor(R.color.label_text_blue));
        work_line_color = a.getColor(R.styleable.TagView_t_line_color, getResources().getColor(R.color.label_blue));
        event_line_color = a.getColor(R.styleable.TagView_t_line_color, getResources().getColor(R.color.label_blue));
        work_text_color = a.getColor(R.styleable.TagView_t_work_text_color, getResources().getColor(R.color.label_text_blue));
        event_text_color = a.getColor(R.styleable.TagView_t_event_text_color, getResources().getColor(R.color.label_text_blue));
        work_label = a.getResourceId(R.styleable.TagView_t_work_label, R.drawable.origin_work);
        event_label = a.getResourceId(R.styleable.TagView_t_event_label, R.drawable.event_blue);
        is_show_icon = a.getBoolean(R.styleable.TagView_t_show_icon, true);
        keep_height = a.getBoolean(R.styleable.TagView_t_keep_height, false);
        ellipsize = a.getBoolean(R.styleable.TagView_t_ellipsize, false);
        a.recycle();
    }

    private int minusWord(TagDetail t, Paint textPaint, int left) throws Exception {
        int border_width = 0;
        for (int i = 0; i < t.getTag_name().length(); i++) {
            String temp = t.getTag_name().substring(0, t.getTag_name().length() - i) + "...";
            if (!TextUtils.isEmpty(t.getWork()) || !TextUtils.isEmpty(t.getEvent_id())) {
                border_width = getIconWidth(temp, textPaint);
            } else {
                border_width = getTextWidth(temp, textPaint);
            }
            if (border_width + left < total_width) {
                t.setShow_name(temp);
                break;
            }
        }
        return border_width;
    }

    private int getTextWidth(String word, Paint textPaint) throws Exception {
        float text_width = textPaint.measureText(word);
        return (int) (text_paddingleft + text_paddingRight + text_width);
    }

    private int getIconWidth(String word, Paint textPaint) throws Exception {
        float text_width = textPaint.measureText(word);
        return (int) (icon_padding_left + icon_padding_right + icon_width + text_width + text_paddingRight);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        final float x = event.getX();
        final float y = event.getY();

        boolean move_flag = false;
        boolean click_flag = false;

        if (tagClickListener != null) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    for (TagDetail t : tlist) {
                        if (x >= t.getRect().left && x <= t.getRect().right && y >= t.getRect().top && y <= t.getRect().bottom) {
                            click_flag = true;
                            break;
                        }
                    }
                    break;
                case MotionEvent.ACTION_MOVE:
                    move_flag = true;
                    break;
                case MotionEvent.ACTION_UP:
                    if (!move_flag) {
                        for (TagDetail t : tlist) {
                            if (x >= t.getRect().left && x <= t.getRect().right && y >= t.getRect().top && y <= t.getRect().bottom) {
                                tagClickListener.onClick(t);
                                break;
                            }
                        }
                    }
                    break;
            }
            return click_flag;
        }
        return false;
    }

    public void setTagViewClick(OnTagClickListener tagClickListener) {
        this.tagClickListener = tagClickListener;
    }

    public interface OnTagClickListener {
        void onClick(TagDetail t);
    }

    public void reset() {
        tlist.clear();
        requestLayout();
    }
}
